package com.qd.panda.wallet.user;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.exception.ApiException;
import com.cdqidi.repeat.annotation.RepeatSubmit;
import com.cdqidi.util.LockTemplate;
import com.cdqidi.util.page.PageUtil;
import com.cdqidi.valid.group.DefaultGroup;
import com.qd.common.panda.domain.entity.wallet.user.UserWalletConsumptionLogDTO;
import com.qd.common.panda.domain.entity.wallet.user.UserWalletDTO;
import com.qd.common.panda.domain.entity.wallet.user.UserWalletRechargeDTO;
import com.qd.common.panda.domain.entity.wallet.user.UserWalletRechargeLogDTO;
import com.qd.common.sys.enums.RemoteEnum;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.common.panda.domain.entity.wallet.user.UserWalletRefundApplyDTO;
import com.qd.panda.service.wallet.user.UserWalletRefundApplyService;
import com.qd.panda.service.stroke.DisplayUtil;
import com.qd.panda.service.wallet.user.UserWalletConsumptionLogService;
import com.qd.panda.service.wallet.user.UserWalletRechargeLogService;
import com.qd.panda.service.wallet.user.UserWalletService;
import com.qd.panda.service.wallet.user.WalletService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Map;

/**
 * 钱包/用户钱包/APP_用户钱包
 *
 * @author sjk
 */
@RequiredArgsConstructor
@Validated
@RestController
@RequestMapping("/app/wallet/userWallet/")
@Slf4j
public class UserWalletController {
    private final UserWalletService userWalletService;
    private final UserWalletRechargeLogService userWalletRechargeLogService;
    private final UserWalletConsumptionLogService userWalletConsumptionLogService;
    private final UserWalletRefundApplyService userWalletRefundApplyService;
    private final WalletService walletService;

    /**
     * 我的钱包
     *
     * @return 记录
     */
    @GetMapping(value = "/myWallet")
    public ApiResultWrapper<Object> myWallet() {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        String userId = SecurityUtils.getLoginUser().getUserId();
        UserWalletDTO userWalletDTO = userWalletService.getByIdDto(SecurityUtils.getLoginUser().getUserId());
        if (null == userWalletDTO) {
            userWalletDTO = new UserWalletDTO();
            userWalletDTO.setUserId(userId);
            userWalletDTO.setRemainingAmount(new BigDecimal("0.00"));
            userWalletDTO.setRemainingGiveAmount(userWalletDTO.getRemainingAmount());
            userWalletDTO.setRemainingRechargeAmount(userWalletDTO.getRemainingAmount());
            userWalletDTO.setRemainingAmountDisplay("0");
            userWalletDTO.setRemainingGiveAmountDisplay("0");
            userWalletDTO.setRemainingRechargeAmountDisplay("0");
        }
        log.info("userId： {},钱包剩余金额： {},剩余充值金额: {},剩余赠送金额: {}", userId, userWalletDTO.getRemainingAmount(), userWalletDTO.getRemainingRechargeAmount(), userWalletDTO.getRemainingGiveAmount());
        return ApiResult.success(userWalletDTO);
    }

    /**
     * 充值
     *
     * @param dto 页面对象
     * @return 页面对象
     */
    @RepeatSubmit
    @PostMapping(value = "/recharge")
    public ApiResultWrapper<Object> recharge(@Validated({DefaultGroup.class}) @RequestBody UserWalletRechargeDTO dto) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        String userId = SecurityUtils.getLoginUser().getUserId();
        dto.setUserId(userId);
//        return RedissonLockTemplate.execute(userId, () -> ApiResult.success(walletService.recharge(dto)), 10, 60);
        return LockTemplate.execute(userId, () -> ApiResult.success(walletService.recharge(dto)));
    }

    /**
     * 充值失败
     *
     * @param map 业务ID
     */
    @PostMapping("/payError")
    public ApiResultWrapper<Object> payError(@Validated @RequestBody Map<String, Object> map) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        Object bid = map.get("thirdPartyOrder");
        Object payStatusObj = map.get("payStatus");
        if (null == bid) {
            return ApiResult.error("业务ID不能为空");
        }
        if (null == payStatusObj) {
            return ApiResult.error("支付状态不能为空");
        }
        int payStatus;
        try {
            payStatus = (int) payStatusObj;
        } catch (Exception e) {
            return ApiResult.error("支付状态值转换错误");
        }
        if (payStatus != DisplayUtil.PAY_STATUS_2 && payStatus != DisplayUtil.PAY_STATUS_4) {
            log.error("支付状态值错误: {}", payStatus);
            return ApiResult.error("支付状态值错误");
        }
        return ApiResult.success(walletService.payError(bid.toString(), payStatus));
    }

    /**
     * 充值记录
     *
     * @param dto 查询参数
     */
    @GetMapping("/rechargeLog")
    public IPage<UserWalletRechargeLogDTO> rechargeLogPage(UserWalletRechargeLogDTO dto) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            throw new ApiException(401, "没有权限操作");
        }
        dto.setUserId(SecurityUtils.getLoginUser().getUserId());
        return userWalletRechargeLogService.page(PageUtil.buildPage(dto), dto);
    }

    /**
     * 消费记录
     *
     * @param dto 查询参数
     */
    @GetMapping("/consumptionLogPage")
    public IPage<UserWalletConsumptionLogDTO> consumptionLogPage(UserWalletConsumptionLogDTO dto) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            throw new ApiException(401, "没有权限操作");
        }
        dto.setUserId(SecurityUtils.getLoginUser().getUserId());
        return userWalletConsumptionLogService.page(PageUtil.buildPage(dto), dto);
    }

    /**
     * 充值详情
     *
     * @param thirdPartyOrder 业务ID
     * @return 详情
     */
    @GetMapping("/payDetail")
    public ApiResultWrapper<Object> payDetail(@Validated @NotNull(message = "业务ID不能为空") String thirdPartyOrder) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        return ApiResult.success(userWalletRechargeLogService.getByIdDto(thirdPartyOrder));
    }

    /**
     * 计算退款金额
     *
     * @return 金额
     */
    @GetMapping(value = "/calculationRefundAmount")
    public ApiResultWrapper<Object> calculationRefundAmount() {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        String userId = SecurityUtils.getLoginUser().getUserId();
        return ApiResult.success(LockTemplate.execute(userId, () -> userWalletRefundApplyService.calculationRefundAmount(userId)));
    }

    /**
     * 申请退款
     *
     * @return 金额
     */
    @PostMapping(value = "/applyRefund")
    public ApiResultWrapper<Object> applyRefund(@Validated @RequestBody UserWalletRefundApplyDTO dto) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            return ApiResult.error(401, "没有权限操作");
        }
        String userId = SecurityUtils.getLoginUser().getUserId();
        LockTemplate.execute(userId, () -> {
            userWalletRefundApplyService.saveAndApproval(dto);
            return null;
        });
        return ApiResult.success();
    }

    /**
     * 退款列表
     *
     * @return 金额
     */
    @GetMapping(value = "/applyRefundPage")
    public IPage<UserWalletRefundApplyDTO> applyRefundPage(UserWalletRefundApplyDTO dto) {
        if (!SecurityUtils.getLoginUser().getRemote().equals(RemoteEnum.MINI_PROGRAM.getCode())) {
            throw new ApiException(401, "没有权限操作");
        }
        String userId = SecurityUtils.getLoginUser().getUserId();
        dto.setApplicant(userId);
        return userWalletRefundApplyService.applyRefundPage(PageUtil.buildPage(dto), dto);
    }

}